package com.catazy.base.data.retrofit

import okhttp3.Request
import okio.Timeout
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

/**
 * 作者: Tao
 * 日期: 2024/12/20
 * 时间: 14:50
 * 描述: ApiResultCall类实现了Call接口，用于封装网络请求的处理逻辑。
 *  它不仅仅是一个委托，还额外处理了API结果的封装，将网络请求的结果转换为ApiResult类型。
 *
 *  @param callDelegate 实际的网络请求调用对象，由其执行具体的网络请求。
 */
internal class ApiResultCall<T>(private val callDelegate: Call<T>) : Call<ApiResult<T>> {

    /**
     * 异步执行网络请求，并根据响应码处理响应结果。
     *
     * @param callback 回调函数，用于处理网络请求的结果。
     */
    override fun enqueue(callback: Callback<ApiResult<T>>) =
        callDelegate.enqueue(object : Callback<T> {
            /**
             * 当网络请求成功时调用。
             * 根据响应码判断请求是否成功，并通过callback返回结果。
             *
             * @param call 实际的网络请求调用对象。
             * @param response 响应对象，包含响应码和响应体。
             */
            override fun onResponse(call: Call<T>, response: Response<T>) {
                response.body()?.let {
                    when (response.code()) {
                        // 成功的响应码范围，将响应体封装为ApiResult.Success
                        in 200..208 -> {
                            callback.onResponse(
                                this@ApiResultCall,
                                Response.success(ApiResult.Success(it))
                            )
                        }

                        // 错误的响应码范围，将错误信息封装为ApiResult.Error
                        in 400..409 -> {
                            callback.onResponse(
                                this@ApiResultCall,
                                Response.success(
                                    ApiResult.Error(
                                        response.code(),
                                        response.message()
                                    )
                                )
                            )
                        }
                    }
                }
            }

            /**
             * 当网络请求失败时调用。
             * 将异常信息封装为ApiResult.Exception，并通过callback返回。
             *
             * @param call 实际的网络请求调用对象。
             * @param throwable 异常对象，表示请求失败的原因。
             */
            override fun onFailure(call: Call<T>, throwable: Throwable) {
                callback.onResponse(this@ApiResultCall, Response.success(ApiResult.Exception(throwable)))
                call.cancel()
            }

        })

    /**
     * 克隆当前Call对象。
     * 用于创建一个新的Call对象，用于重新执行网络请求。
     *
     * @return 克隆后的ApiResultCall对象。
     */
    override fun clone(): Call<ApiResult<T>> = ApiResultCall(callDelegate.clone())

    /**
     * 执行网络请求并同步返回结果。
     * 本实现中不支持此操作，会抛出UnsupportedOperationException异常。
     *
     * @throws UnsupportedOperationException 总是抛出此异常，因为此操作不被支持。
     */
    override fun execute(): Response<ApiResult<T>> =
        throw UnsupportedOperationException("ResponseCall不支持execute")

    /**
     * 判断网络请求是否已经执行。
     *
     * @return true如果网络请求已经执行，否则返回false。
     */
    override fun isExecuted(): Boolean = callDelegate.isExecuted

    /**
     * 取消网络请求。
     * 如果网络请求已经执行但尚未完成，此方法将取消该请求。
     */
    override fun cancel() = callDelegate.cancel()

    /**
     * 判断网络请求是否已被取消。
     *
     * @return true如果网络请求已被取消，否则返回false。
     */
    override fun isCanceled(): Boolean = callDelegate.isCanceled

    /**
     * 获取网络请求对象。
     *
     * @return Request对象，表示将要执行的网络请求。
     */
    override fun request(): Request = callDelegate.request()

    /**
     * 获取网络请求的超时设置。
     *
     * @return Timeout对象，表示网络请求的超时配置。
     */
    override fun timeout(): Timeout = callDelegate.timeout()
}
